package views.components;

import java.util.ArrayList;
import java.util.List;

import utils.AppUtils;
import utils.MessageUtils;
import utils.ReflectionUtils;
import views.interfaces.IParameter;
import app.ApplicationManager;
import app.structure.MenuFrm;
import app.structure.MenuProc;
import app.structure.MenuStruct;

import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.addon.jpacontainer.util.HibernateLazyLoadingDelegate;
import com.vaadin.data.util.filter.Like;
import com.vaadin.data.util.filter.Or;
import com.vaadin.event.FieldEvents.TextChangeEvent;
import com.vaadin.event.FieldEvents.TextChangeListener;
import com.vaadin.server.Resource;
import com.vaadin.server.ThemeResource;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.MenuBar;
import com.vaadin.ui.MenuBar.Command;
import com.vaadin.ui.MenuBar.MenuItem;
import com.vaadin.ui.Notification;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;

import config.Parameters;
import controllers.control.BaseController;
import dao.interfaces.IBase;

@SuppressWarnings("serial")
// OJO: It does NOT work as Custom Component
/**
 * Clase que crea un menu y mostra formularis
 * @author jack
 *
 */
public class BarraMenu extends VerticalLayout implements IParameter {

	private String storedId;
	private VerticalLayout root;
	private Class<IBase> myClass;
	private Class<BaseController> myControllerClass;
	private int secLevel;

	public BarraMenu(List<MenuStruct> menuStructs, int secLevel) {
		this.secLevel = secLevel;
		if (!menuStructs.isEmpty()) {

			MenuBar menuBar = new MenuBar();
			MenuItem menuItem;
			List<MenuStruct> subMenuStructs;

			for (MenuStruct menuStruct : menuStructs) {

				if (secLevel >= menuStruct.getSecLevel()) {

					menuItem = menuBar.addItem(
							MessageUtils.getI18n(menuStruct.getName()), null);
					subMenuStructs = menuStruct.getMenuSt();

					if (!subMenuStructs.isEmpty())
						fillItem(menuItem, subMenuStructs);

				}
			}

			addComponent(menuBar);
			setComponentAlignment(menuBar, Alignment.MIDDLE_CENTER);
		}

	}

	private void fillItem(MenuItem menuItem, List<MenuStruct> menuStructs) {

		if (!menuStructs.isEmpty()) {

			Resource icon;
			MenuItem submenuItem;
			List<MenuStruct> subMenuStructs;

			for (MenuStruct menuStruct : menuStructs) {
				if (menuStruct == null) {
					continue;
				}
				if (secLevel >= menuStruct.getSecLevel()) {
					icon = getRes(menuStruct.getTyp());

					submenuItem = menuItem.addItem(
							MessageUtils.getI18n(menuStruct.getName()), icon,
							getCommand(menuStruct));
					subMenuStructs = menuStruct.getMenuSt();

					if (!subMenuStructs.isEmpty())
						fillItem(submenuItem, subMenuStructs);
				}
			}
		}
	}

	private void showForm(MenuFrm mnuFrm) throws Exception {

		crearClases(mnuFrm.getClazz());

		final JPAContainer<IBase> jpaContainer = JPAContainerFactory.make(
				myClass, Parameters.DB_DATA_SOURCE);

		// fique un lazy loader
		jpaContainer.getEntityProvider().setLazyLoadingDelegate(
				new HibernateLazyLoadingDelegate());

		final TablaPaginada tablaPaginada = new TablaPaginada(myClass,
				myControllerClass, jpaContainer, this, secLevel,
				mnuFrm.getView());

		HorizontalLayout controls = tablaPaginada.createControls();

		Button btExecuteAction = new Button(MessageUtils.getI18n("executar"),
				tablaPaginada);
		
		if (secLevel > Parameters.INSERTAR) {

			Button btAdd = new Button(MessageUtils.getI18n("add"),
					new ClickListener() {

						@Override
						public void buttonClick(ClickEvent event) {

							try {

								BaseController newInstance = myControllerClass
										.newInstance();
								newInstance.insertar(jpaContainer);

							} catch (Exception e) {
								Notification.show(e.getMessage());
							}
						}
					});
			controls.addComponentAsFirst(btAdd);
		}
		
		TextField searchField = new TextField();
		searchField.setInputPrompt(MessageUtils.getI18n("buscar"));

		searchField.addTextChangeListener(new TextChangeListener() {

			@Override
			public void textChange(TextChangeEvent event) {

				String textFilter = event.getText();

				jpaContainer.setApplyFiltersImmediately(false);
				jpaContainer.removeAllContainerFilters();

				if (textFilter != null && !textFilter.equals("")) {

					ArrayList<String> paraules = ReflectionUtils
							.getBuscarFields(myClass);
					Or or;

					if (paraules != null) {
						Or[] condicions = new Or[paraules.size()];

						for (int i = 0; i < paraules.size(); i++) {

							String paraula = paraules.get(i);
							condicions[i] = new Or(new Like(paraula, textFilter
									+ "%", false));
						}

						or = new Or(condicions);

					} else {
						or = new Or(new Like("description", textFilter + "%",
								false), new Like("notes", textFilter + "%",
								false));

					}
					jpaContainer.addContainerFilter(or);

				}
				jpaContainer.applyFilters();

				tablaPaginada.refreshRowCache();
			}

		});

		controls.addComponentAsFirst(btExecuteAction);
		controls.addComponent(searchField);
		controls.setSizeUndefined();
		controls.setSpacing(true);
		controls.setMargin(true);

		int componentCount = getComponentCount();
		if (componentCount == 1) {
			root = new VerticalLayout(tablaPaginada, controls);
			root.setMargin(true);
			root.setSpacing(true);
			addComponent(root);
		} else if (componentCount == 2) {
			removeComponent(root);
			root = new VerticalLayout(tablaPaginada, controls);
			root.setMargin(true);
			root.setSpacing(true);
			addComponent(root);
		}

	}
	

	@SuppressWarnings("unchecked")
	private void crearClases(String clase) {
		try {
			myClass = (Class<IBase>) Class.forName(clase);
			String controllerName = myClass.getCanonicalName().replace(
					Parameters.DAO_PACKAGE, Parameters.CONTROLLER_PACKAGE)
					+ Parameters.CONTROLLER_SUFFIX;

			myControllerClass = (Class<BaseController>) Class
					.forName(controllerName);

		} catch (ClassNotFoundException e) {
			if (myControllerClass == null) {
				try {
					myControllerClass = (Class<BaseController>) Class
							.forName("controllers.control.BaseController");
				} catch (ClassNotFoundException e1) {
					Notification.show(e1.getMessage());
				}
			}
		}
	}

	private void execProcedure(MenuProc mnuFrm) {
	}

	private void execReport(MenuProc mnuFrm) {
		
	}

	private void execTransaction(MenuProc mnuFrm) {
	}

	private Command getCommand(final MenuStruct mnuS) {

		Command myCommand;
		final ApplicationManager appMngr = AppUtils.getApplicationManager();

		switch (mnuS.getTyp().toUpperCase()) {
		case "F":
			myCommand = new Command() {
				@Override
				public void menuSelected(final MenuItem selectedItem) {
					try {
						showForm(appMngr.getForm(mnuS.getId()));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			};
			break;
		case "P":
			myCommand = new Command() {
				@Override
				public void menuSelected(final MenuItem selectedItem) {
					execProcedure(appMngr.getProc(mnuS.getId()));
				}
			};
			break;
		case "R":
			myCommand = new Command() {
				@Override
				public void menuSelected(final MenuItem selectedItem) {
					execReport(appMngr.getProc(mnuS.getId()));
				}
			};
			break;
		case "T":
			myCommand = new Command() {
				@Override
				public void menuSelected(final MenuItem selectedItem) {
					execTransaction(appMngr.getProc(mnuS.getId()));
				}
			};
			break;
		default:
			myCommand = null;
			break;
		}
		return myCommand;

	}

	private Resource getRes(String type) {

		Resource icon;

		switch (type.toUpperCase()) {
		case "F":// 1. Form
			icon = new ThemeResource(Parameters.ICO_COMMON_PATH + "form.ico");
			break;
		case "P":// 2. Procedure
			icon = new ThemeResource(Parameters.ICO_COMMON_PATH
					+ "procedure.ico");
			break;
		case "R":// 3. Report
			icon = new ThemeResource(Parameters.ICO_COMMON_PATH + "report.ico");
			break;
		case "T":// 4. Transaction
			icon = new ThemeResource(Parameters.ICO_COMMON_PATH
					+ "transaction.ico");
			break;
		case "M":// 5. Folder
			icon = new ThemeResource(Parameters.ICO_COMMON_PATH + "folder.ico");
			break;
		default:// 6. Error in type (unknown type)
			icon = new ThemeResource(Parameters.ICO_COMMON_PATH
					+ "question.ico");
			break;
		}

		return icon;
	}

	@Override
	public String getParameter() {
		return storedId;
	}

	@Override
	public void setParameter(String parameter) {
		this.storedId = parameter;
	}
}
